/**
 * <p>ClassName: CloudMaker</p>
 * <p>Description: TODO<p>
 * <p>date 2015-6-2 下午8:40:04<p>
 * @author zhangzh
 */

package com.hollycrm.hollysqm.core.waveform.wordcloud;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.text.NumberFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;

public class CloudMaker {
		interface DataHandler {
			void doHandler(HashMap<Integer, HashMap<String, Double>> data);
		}

		interface ErrorHandler {
			void doHandler(Throwable t);

			public static final ErrorHandler PRINTER = new ErrorHandler() {
				public void doHandler(Throwable t) {
					t.printStackTrace();
				}
			};
		}

		/**
		 * 核心类，大文件数据处理器
		 */
		class BigFileProcessor {
			/**
			 * 致命毒药，用于干掉处理数据的线程。
			 */
			public final Object POISON = new Object();
			private BlockingQueue<Object> queue = new ArrayBlockingQueue<Object>(
					1000);
			private ErrorHandler errorHandler = ErrorHandler.PRINTER;
			/**
			 * 用于终止读取线程，非强制终止。
			 */
			private volatile boolean running = false;
			/**
			 * 数据读取线程
			 */
			private Thread fileReader;
			/**
			 * 数据处理线程
			 */
			private Thread[] proccessors;

			/* 获取所有类别 */
			private void getAllClass(List<HashMap<String, Double>> explain, BlockingQueue<Object> queue)
					throws Exception {
				for (int i = 0; i < explain.size(); i++) {
					HashMap<String, Double> result = explain.get(i);
					HashMap<Integer, HashMap<String, Double>> part = new HashMap<Integer, HashMap<String, Double>>();
					part.put(i, result);
					queue.put(part);
				}
			}

			public BigFileProcessor(final List<HashMap<String, Double>> explain,
					final DataHandler handler) {
				fileReader = new Thread(new Runnable() {
					public void run() {
						try {
							getAllClass(explain, queue);
						} catch (Throwable t) {
							errorHandler.doHandler(t);
						} finally {
							try {
								queue.put(POISON);
							} catch (InterruptedException e) {
								errorHandler.doHandler(e);
							}
						}
					}
				}, "reader_thread");
				// 默认创建的线程数，与CPU处理的内核数相同，楼主可以自行更改。
				proccessors = new Thread[Runtime.getRuntime().availableProcessors()];

				Runnable worker = new Runnable() {
					public void run() {
						try {
							for (;;) {
								Object obj = queue.take();
								if (obj == POISON) {
									queue.put(obj);
									break;
								} else {
									HashMap<Integer, HashMap<String, Double>> data = (HashMap<Integer, HashMap<String, Double>>) obj;
									handler.doHandler(data);
								}
							}
						} catch (Throwable t) {
							errorHandler.doHandler(t);
						}
					}
				};
				for (int i = 0; i < proccessors.length; i++) {
					proccessors[i] = new Thread(worker, "proccessor-thread_" + i);
				}
			}

			public void setErrorHandler(ErrorHandler errorHandler) {
				this.errorHandler = errorHandler;
			}

			/**
			 * 开启处理过程
			 */
			public synchronized void start() {
				if (running)
					return;
				running = true;
				fileReader.start();
				for (int i = 0; i < proccessors.length; i++) {
					proccessors[i].start();
				}
			}

			/**
			 * 中断处理过程，非强制中断
			 */
			public synchronized void shutdown() {
				if (running) {
					running = false;
				}
			}

			/**
			 * 试图等待整个处理过程完毕
			 */
			public void join() {
				try {
					fileReader.join();
				} catch (InterruptedException e) {
					errorHandler.doHandler(e);
				}
				for (int i = 0; i < proccessors.length; i++) {
					try {
						proccessors[i].join();
					} catch (InterruptedException e) {
						errorHandler.doHandler(e);
					}
				}
			}
		}

		/**
		 * 词云生成方法
		 * 
		 */
		public void wordCloud(List<HashMap<String, Double>> explain,final String imgPath,final Double size) {
			DataHandler dataHandler = new DataHandler() {
				public void doHandler(
						HashMap<Integer, HashMap<String, Double>> data) {
					Iterator<Integer> item = data.keySet().iterator();
					int i = 0;
					if (item.hasNext())
						i = item.next();
					String fileName = imgPath + "Classes" + i + ".png";
					String bgPic = null;
					String waterMarkPic = null;
					int width = 1024;
					int height = 768;
					String fontName = "微软雅黑";

					HashMap<String, Double> result = data.get(i);
					List<WordMapping> words = new ArrayList<WordMapping>();
					Iterator<String> it = result.keySet().iterator();
					while(it.hasNext()) {
						String word=it.next();
						Double value = (1 - result.get(word)) * 1000;
						int count = value.intValue();
						words.add(new WordMapping(word, count));
					}

					if (words.size() < 1) {
						return;
					}

					int swidth = width / 20 * 18, sheight = height / 20 * 18;

					BufferedImage bi = WordsThumb.createWordsThumb(words, width,
							sheight, fontName, null, null);

					BufferedImage bg = null;
					BufferedImage wm = null;
					Float fgAlpha = Float.valueOf(0.8F);
					Float wmAlpha = Float.valueOf(1.0F);
					if (bgPic != null)
						try {
							bg = ImageIO.read(new FileInputStream(bgPic));
						} catch (FileNotFoundException e) {

							e.printStackTrace();
						} catch (IOException e) {

							e.printStackTrace();
						}
					if (waterMarkPic != null) {
						try {
							wm = ImageIO.read(new FileInputStream(waterMarkPic));
						} catch (FileNotFoundException e) {

							e.printStackTrace();
						} catch (IOException e) {

							e.printStackTrace();
						}
					}
					bi = WordsThumb.mixImages(new BufferedImage[] { bg, bi, wm },
							new Float[] { Float.valueOf(1.0F), fgAlpha, wmAlpha },
							bi.getWidth(), bi.getHeight());

					File file = new File(fileName);

					if (file.exists()) {
						file.delete();
					}

					List<String> photos = new ArrayList<String>();
					photos.add("http://www.hollycrm.com");

					BufferedImage img = null;
					double percent = (double) result.size() / size;
					NumberFormat nt = NumberFormat.getPercentInstance();
					nt.setMaximumIntegerDigits(3);
					nt.setMinimumFractionDigits(2);
					img = MakeCollage.make("Classes:" + i + " 数量:" + result.size()
							+ " 占比:" + nt.format(percent), bi, photos, width,
							height);

					try {
						ImageIO.write(img, "png", file);
					} catch (IOException e) {

						e.printStackTrace();
					}

				}
			};

			BigFileProcessor processor = new BigFileProcessor(explain, dataHandler);
			processor.start();
			processor.join();
		}

		/**
		 * @param args
		 * @throws IOException
		 */
		public static void main(String[] args) throws IOException {
			long start = System.currentTimeMillis();
			long end = System.currentTimeMillis();
			System.out.println("[耗时：" + (end - start) / 1000 + "ms "
					+ (end - start) / (1000 * 60) + "分钟]");
		}


}
